namespace study3_01 {


    // 1.1泛型
    function identity<T>(arg: T) {
        return arg
    }
    console.log(identity<string>('asdad')); // asdad
    console.log(identity<number>(45235)); // 45235
    console.log(identity<boolean>(true)); // true

    // 把泛型变量T当作类型的一部分，而不是整个类型，增加了灵活性
    function loggingIdentity<T>(arg: T[]): T[] {
        console.log(arg.length); // 3 // 2 // 5
        return arg
    }
    console.log(loggingIdentity<string>(['ert', 'dfg', 'fyj'])); // [ 'ert', 'dfg', 'fyj' ]
    console.log(loggingIdentity<number>([123, 234])); // [ 123, 234 ]
    console.log(loggingIdentity<boolean>([true, false, false, false, true])); // [ true, false, false, false, true ]


    // 我们也可以使用不同的泛型参数名，只要在数量上和使用方式上能对应上就行
    function Sub<T, U>(a: T, b: U): Array<T | U> {
        let params: Array<T | U> = [a, b]
        return params
    }
    console.log(Sub<Boolean, number>(false, 1)); // [ false, 1 ]


    // 对象字面量
    let foo: { <T>(arg: T): T }
    foo = function <T>(arg: T): T {
        return arg
    }
    console.log(foo<number>(123)); // 123
    console.log(foo<string>('asd')); // asd

    // 泛型约束
    // 我们期望在一个泛型的变量上面，获取其length参数，但是，有的数据类型是没有length属性的
    // 这个时候就可以使用泛型约束

    interface Len {
        length: number

    }
    function getLength<T extends Len>(arg: T): number {
        return arg.length
    }
    console.log(getLength<string>('asadf'));  // 5

    // 使用keyof约束对象
    // 
    function prop<T, K extends keyof T>(obj: T, key: K) {
        return obj[key]
    }
    let o = { a: 12, b: 23, c: 34 }
    console.log(prop(o, 'a')); // 12
    console.log(prop(o, 'b')); // 23
    console.log(prop(o, 'c')); // 34
    // let o = { a: 12, b: 23, c: 34 }
    // console.log(o['a']);
    // console.log(o.a);
    // prop(o, 'd') // 类型“"d"”的参数不能赋给类型“"a" | "b" | "c"”的参数。



    // 泛型类
    // 泛型类看上去与泛型接口差不多。泛型类使用(<>)括起泛型类型，跟在类名后面
    // 使用的时候确定类型 new Sub<number>()
    class Sub2<T> {
        arrt: T[] = [];
        add(a: T): T[] {
            return [a]
        }

    }

    let s = new Sub2<number>()
    s.arrt = [123, 465, 768]
    console.log(s.add(345)); // [ 345 ]
    console.log(s); // Sub2 { arrt: [ 123, 465, 768 ] }
    console.log(s.arrt); // [ 123, 465, 768 ]


    let str = new Sub2<string>()
    str.arrt = ['qwe', 'sad', 'asd', 'asdd']
    console.log(str.add('oih')); // [ 'oih' ]
    console.log(str); // Sub2 { arrt: [ 'qwe', 'sad', 'asd', 'asdd' ] }
    console.log(str.arrt); // [ 'qwe', 'sad', 'asd', 'asdd' ]








}